/**
 * @class 静默预加载器
 * @author DuskyHuang 圣子
 * @description 偷偷滴、偷偷滴把需要资源加载了！
*/

import { _decorator, Material, macro, resources, Texture2D } from 'cc';
import { Mediator } from 'cfw';
import { LogProxy, user } from 'proxies';
import { Task, } from 'notifications';
const { ccclass, property, type } = _decorator;

@ccclass('cocosmos.preload-task')
class PreloadTask {
    @property public taskName: string = '';
    @property public dynamicPath: string = '';
    @property public matKey: string = '';
    @property(Material) public sharedMaterial: Material = null;
    @property public isTex: boolean = true;
    public launched: boolean = false;
}

@ccclass('cocosmos.mute-preloader')
export class MutePreloader extends Mediator {

    @type([PreloadTask]) public tasks: PreloadTask[] = [];
    @property({ slide: true, range: [0, 10, 0.1] }) public interval: time.sec = 3;
    @property({ slide: true, range: [0, 10, 0.1] }) public delay: time.sec = 5;

    public resetTimes(interval: time.sec, delay: time.sec): void {
        this.unscheduleAllCallbacks();
        this.interval = interval;
        this.delay = delay;
        this.schedule(() => this.doTaskOnce(), this.interval, macro.REPEAT_FOREVER, this.delay);
    }

    protected onLoad(): void {
        this.on(Task.Load.DYNAMIC_TEX, this.loadDynamicTexImmediately);
    }

    protected start(): void {
        this._guideDilatory();
        this.schedule(() => this.doTaskOnce(), this.interval, macro.REPEAT_FOREVER, this.delay);
    }

    private _guideDilatory(): void {
        if (!user.guided) {
            this.interval++;
            this.delay += 3;
        }
    }

    protected doTaskOnce(task?: PreloadTask): void {
        let chosen = task;
        if (!chosen) {
            chosen = this.tasks.find(task => !task.launched);
        }
        if (chosen) {
            chosen.launched = true;
            const { isTex, dynamicPath, matKey, sharedMaterial } = chosen;
            const path = (isTex ? 'textures/' : '') + dynamicPath + (isTex ? '/texture' : '')
            resources.load(path, Texture2D, (err, tex) => {
                if (err) {
                    console.error("[load tex failed]", path);
                    chosen.launched = false;
                } else {
                    tex.addRef();
                    this._texes[dynamicPath] = tex;
                    if (sharedMaterial && matKey) {
                        sharedMaterial.setProperty(matKey, tex);
                        LogProxy.PRINT_LOAD_TASK && console.info("[task finished]", "material-tex:", path);
                    } else {
                        LogProxy.PRINT_LOAD_TASK && console.info("[task finished]", "fetch-tex:", path);
                    }
                }
            });
        } else {
            this.unscheduleAllCallbacks();
        }
    }

    protected loadDynamicTexImmediately(name: string): void {
        const task = this.tasks.find(task => task.taskName === name);
        if (!task) return console.error("[no task named]", name);
        if (task.launched) return console.warn("[task already launched]", name);
        this.doTaskOnce(task);
    }

    private _texes: Record<string, Texture2D> = {};
}